home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / video / fly8111-.000 / fly8111- / fly8 / utils / max2mac.c < prev   
C/C++ Source or Header  |  1979-12-31  |  7KB  |  417 lines

  1. /* --------------------------------- max2mac.c ------------------------------ */
  2.  
  3. /* This is part of the flight simulator 'fly8'.
  4.  * Author: Eyal Lebedinsky (eyal@ise.canberra.edu.au).
  5. */
  6.  
  7. /* Read a text macro definition and build a macro file. See 'mac2max'.
  8. */
  9.  
  10. #include "fly.h"
  11. #include "keyname.h"
  12.  
  13.  
  14. /* This is needed since "fly.h" defines it.
  15. */
  16. struct status    NEAR st = {0};
  17.  
  18. static Ulong lineno = 1L, column = 0L, errs = 0L;
  19. static int    eof = 1, pushback = 0;
  20. static int    pushbuff[10] = {0};
  21. static char tabCTRL[] = "@abcdefghijklmnopqrstuvwxyz[\\]^_";
  22. static Ushort buf_str[1024] = {0};
  23.  
  24. static int NEAR
  25. putshort (short i, FILE *f)
  26. {
  27.     if (errs)
  28.         return (0);
  29.  
  30.     fputc (0x00ff&(i>>8), f);
  31.     if (ferror (f)) {
  32.         ++errs;
  33.         fprintf (stderr, "write error\n");
  34.         return (1);
  35.     }
  36.  
  37.     fputc (0x00ff&i, f);
  38.     if (ferror (f)) {
  39.         ++errs;
  40.         fprintf (stderr, "write error\n");
  41.         return (1);
  42.     }
  43.  
  44.     return (0);
  45. }
  46.  
  47. static int NEAR
  48. keyval (int c)
  49. {
  50.     if (c >= 0 && c < 32)
  51.         c = tabCTRL[c] | K_CTRL;
  52.     return (c);
  53. }
  54.  
  55. static int NEAR
  56. nlfgetc (FILE *f)
  57. {
  58.     int    c;
  59.  
  60.     if (pushback) {
  61.         c = pushbuff[--pushback];
  62.         return (c);
  63.     }
  64.  
  65.     if (eof)
  66.         return (EOF);
  67.  
  68.     c = fgetc (f);
  69.     ++column;
  70.     if ('\n' == c) {
  71.         ++lineno;
  72.         column = 0;
  73.     } else if (EOF == c)
  74.         eof = 1;
  75.  
  76.     return (c);
  77. }
  78.  
  79. static Ulong NEAR
  80. eatline (FILE *f)
  81. {
  82.     int    c;
  83.  
  84.     do {
  85.         c = nlfgetc (f);
  86.     } while (EOF != c && '\n' != c);
  87.     return (EOF == c ? VK_EOF : (Ulong)c);
  88. }
  89.  
  90. static int NEAR
  91. getbase (FILE *f, int base, int n, int c)
  92. {
  93.     int    i;
  94.  
  95.     for (i = 0;;) {
  96.         if (c >= '0' && c <= '9')
  97.             c -= '0';
  98.         else if (c >= 'a' && c <= 'f')
  99.             c -= 'a' - 10;
  100.         else if (c >= 'A' && c <= 'F')
  101.             c -= 'A' - 10;
  102.         else {
  103.             pushbuff[pushback++] = c;
  104.             break;
  105.         }
  106.         if (c >= base)
  107.             break;
  108.         i = i * base + c;
  109.         if (--n < 0)
  110.             break;
  111.         c = nlfgetc (f);
  112.     }
  113.  
  114.     if (i >= 256) {
  115.         ++errs;
  116.         printf ("escaped value too big at %ld:%ld\n",
  117.             lineno, column);
  118.         i &= 0x00ff;
  119.     }
  120.     return (i);
  121. }
  122.  
  123. static int NEAR
  124. getescape (FILE *f)
  125. {
  126.     int    c;
  127.  
  128.     c = nlfgetc (f);
  129.  
  130.     switch (c) {
  131.     case 'a':
  132.         c = 'g';
  133.         break;
  134.     case 'b':
  135.         c = 'h';
  136.         break;
  137.     case 'e':
  138.         c = '[';
  139.         break;
  140.     case 'f':
  141.         c = 'l';
  142.         break;
  143.     case 'n':
  144.         c = 'm';
  145.         break;
  146.     case 'r':
  147.         c = 'j';
  148.         break;
  149.     case 't':
  150.         c = 'i';
  151.         break;
  152.     case 'v':
  153.         c = 'k';
  154.         break;
  155.     case '\n':
  156.         c = -1;        /* traditional line break */
  157.         goto raw;
  158.     case '0':
  159.         c = keyval (getbase (f, 8, 3, '0'));
  160.         goto raw;
  161.     case '1':
  162.     case '2':
  163.     case '3':
  164.     case '4':
  165.     case '5':
  166.     case '6':
  167.     case '7':
  168.     case '8':
  169.     case '9':
  170.         c = keyval (getbase (f, 10, 2, c));
  171.         goto raw;
  172.     case 'x':
  173.         c = keyval (getbase (f, 16, 2, '0'));
  174.         goto raw;
  175.     default:
  176.         goto raw;
  177.     }
  178.     c |= K_CTRL;
  179. raw:
  180.     return (c);
  181. }
  182.  
  183. static int NEAR
  184. getstring (FILE *f)
  185. {
  186.     int    c, n;
  187.  
  188.     for (n = 0;;) {
  189.         c = nlfgetc (f);
  190.         if (EOF == c) {
  191.             ++errs;
  192.             printf ("EOF inside string at %ld:%ld\n",
  193.                 lineno, column);
  194.             n = -1;
  195.             break;
  196.         }
  197.         if ('\\' == c) {
  198.             c = getescape (f);
  199.             if (-1 == c)
  200.                 continue;
  201.         } else if ('"' == c)
  202.             break;
  203.         else if ('\n' == c)        /* simplified line break */
  204.             continue;
  205.         else
  206.             c = keyval (c);
  207.         if (n >= rangeof (buf_str)) {
  208.             ++errs;
  209.             printf ("string too long at %ld:%ld\n",
  210.                 lineno, column);
  211.             continue;
  212.         }
  213.         buf_str[n++] = (Ushort)c;
  214.     }
  215.     return (n);
  216. }
  217.  
  218. static Ulong NEAR
  219. getterm (FILE *f)
  220. {
  221.     char    keyname[32+1];
  222.     int    n, i, c;
  223.  
  224. retry:
  225.     for (n = 0;;) {
  226.         c = nlfgetc (f);
  227.         if (EOF == c) {
  228.             if (n)
  229.                 break;
  230.             return (VK_EOF);
  231.         }
  232.         if (isspace (c)) {
  233.             if (n)
  234.                 break;
  235.             continue;
  236.         }
  237.         if ('\\' == c) {
  238.             if (n) {
  239.                 ++errs;
  240.                 printf ("bad escape at %ld:%ld\n",
  241.                     lineno, column);
  242.                 continue;
  243.             }
  244.             c = getescape (f);
  245.             if (-1 == c)
  246.                 continue;
  247.             return (c);
  248.         }
  249.         if (n < sizeof (keyname) - 1) {
  250.             if (0 == n) {
  251.                 if ('"' == c)
  252.                     return (VK_STR);
  253.                 if ('#' == c)
  254.                     return (VK_COM);
  255.             }
  256.             keyname[n++] = (char)c;
  257.         } else
  258.             {/* truncate... */}
  259.     }
  260.     keyname[n] = '\0';
  261.  
  262. /* Look word up
  263. */
  264.     for (i = 0; k_name[i].name; ++i) {
  265.         if (!stricmp (k_name[i].name, keyname))
  266.             return (k_name[i].value);
  267.     }
  268.  
  269.     if (1 == n)
  270.         return (keyval(*(Uchar *)keyname));
  271.  
  272.     ++errs;
  273.     printf ("bad token '%s' at %ld:%ld\n", keyname, lineno, column);
  274.     if (EOF == c)
  275.         return (VK_EOF);
  276.  
  277.     goto retry;
  278. }
  279.  
  280. static Ulong NEAR
  281. getkey (FILE *f)
  282. {
  283.     Ulong    c, key;
  284.  
  285.     for (key = 0L;;) {
  286.         c = getterm (f);
  287.         if (VK_EOF == c) {
  288.             if (key) {
  289.                 ++errs;
  290.                 printf ("unexpected end of file at %ld:%ld\n",
  291.                     lineno, column);
  292.             }
  293.             return (VK_EOF);
  294.         } else if (VK_DEF == c) {
  295.             if (key) {
  296.                 ++errs;
  297.                 printf ("bad key preceding 'def' at %ld:%ld\n",
  298.                     lineno, column);
  299.             }
  300.             key = VK_DEF;
  301.         } else if (VK_COM == c) {
  302.             if (key) {
  303.                 ++errs;
  304.                 printf ("bad key preceding '##' %ld:%ld\n",
  305.                     lineno, column);
  306.             }
  307.             key = 0L;
  308.             c = eatline (f);
  309.             if (VK_EOF == c)
  310.                 return (VK_EOF);
  311.         } else if (VK_STR == c) {
  312.             if (key) {
  313.                 ++errs;
  314.                 printf ("bad key preceding '#\"' %ld:%ld\n",
  315.                     lineno, column);
  316.             }
  317.             return (VK_STR);
  318.         } else {
  319.             key |= c;
  320.             if (c & K_RAW)
  321.                 return (key);
  322.         }
  323.     }
  324.     /* never reached */
  325. }
  326.  
  327. static Ushort definition[1024] = {0};
  328.  
  329. static void NEAR
  330. buildmac (char *mname)
  331. {
  332.     FILE    *mac;
  333.     int    i, n;
  334.     Ulong    c;
  335.  
  336.     mac = fopen (mname, WBMODE);
  337.     if (!mac) {
  338.         ++errs;
  339.         printf ("open '%s' failed", mname);
  340.         return;
  341.     }
  342.     eof = 0;
  343.     pushback = 0;
  344.  
  345.     for (;;) {
  346.         c = getkey (stdin);
  347.         if (VK_EOF == c)
  348.             break;
  349.         if (!(VK_DEF & c)) {
  350.             ++errs;
  351.             printf ("'def' not found at %ld:%ld\n", lineno, column);
  352.             continue;
  353.         }
  354. def:
  355.         if (putshort ((short)c, mac))    /* macro name */
  356.             break;
  357.         for (n = 0;;) {
  358.             c = getkey (stdin);
  359.             if (VK_EOF == c || (VK_DEF & c))
  360.                 break;
  361.             if (VK_STR == c) {
  362.                 i = getstring (stdin);
  363.                 if (i <= 0)
  364.                     continue;
  365.                 if (n+i > rangeof (definition)) {
  366.                     ++errs;
  367.                     printf ("macro too long at %ld:%ld\n",
  368.                         lineno, column);
  369.                 } else {
  370.                     memcpy (definition+n, buf_str, 2*i);
  371.                     n += i;
  372.                 }
  373.                 continue;
  374.             }
  375.             if (n >= rangeof (definition)) {
  376.                 ++errs;
  377.                 printf ("macro too long at %ld:%ld\n",
  378.                     lineno, column);
  379.                 continue;
  380.             }
  381.             definition[n++] = (Ushort)c;
  382.         }
  383.         if (0 == n) {
  384.             ++errs;
  385.             printf ("empty macro at %ld:%ld\n", lineno, column);
  386.         }
  387.         if (putshort ((short)n, mac))    /* macro length */
  388.             break;
  389.         for (i = 0; i < n; ++i) {    /* macro body */
  390.             if (putshort (definition[i], mac))
  391.                 goto ret;
  392.         }
  393.         if (VK_DEF & c)
  394.             goto def;
  395.         if (VK_EOF == c)
  396.             break;
  397.     }
  398. ret:
  399.     fclose (mac);
  400.     eof = 1;
  401.     pushback = 0;
  402. }
  403.  
  404. int
  405. main (int argc, char *argv[])
  406. {
  407.     char    *mname;
  408.  
  409.     if (argc < 2 || !(mname = argv[1]))
  410.         mname = "fly.mac";
  411.  
  412.     buildmac (mname);
  413.  
  414.     exit (0);
  415.     return (0);
  416. }
  417.